#include "app.H"
#include "kernel.H"
#include "scidriver.h"


//#include	"driver\sci\ports\sciconfig.h"                                         
//#include	"driver\sci\ports\sci\ports\scihdports.h"     

//INT8U	wBinaryMode=0;
//INT8U	wHighByte=0;
//INT8U	wLowByte=0;
//INT8U	wSendHighHalfByte=0;

/************************************************************************************
*constant define																	*
*************************************************************************************/
#define		cSciTypeSci				0			/*		normal sci moule 			*/
#define		cSciTypeIo2Sci			1			/*		io2sci module				*/
#define		cSciTypeCapSci			2			/*		CapSci module				*/

#define		cSciTxRdy				0
#define		cSciTxBusy				1

#define		cSciRxBufEmpty			1
#define		cSciRxRdy				0

#define		cQBufNormal				0
#define		cQBufFull				1
#define		cQBufEmpty				2


/************************************************************************************
*Queue structure																	*
*************************************************************************************/
typedef	struct{
				INT8U	*pIn;
				INT8U	*pOut;
				INT8U	*pStart;
				INT16U	length;
				INT16U 	size;
			}QUEUE;
/************************************************************************************
*Sci structure																		*
*Including  tranmit and receive queue structure and Tx,Rx threshold control variabls*
*************************************************************************************/
typedef	struct{
				INT8U	bTxStatus;
				INT8U	ubTxLength;
				INT8U	*pbTx;
				QUEUE	*pqRx;
				//INT8U	bSciType;
			}	SciStruct;



/************************************************************************************
*List of Sci structure and queue 													*
*************************************************************************************/
SciStruct	SciList[MAX_SCI_NO];
QUEUE		QList[MAX_SCI_NO];
SciStruct	*pSciIndex[MAX_SCI_NO];
INT8U		bSciRxBuf[MAX_SCI_BUF_SIZE];
//INT8U		*pSciBuf;
INT8U		*pSciBuf=bSciRxBuf;	
INT8U		bSciNo=0;
			
void	sQInit(QUEUE *pq,INT8U *start,INT16U size); 
INT8U	sQDataIn(QUEUE	*pq,INT8U data); 
INT8U	sQDataOut(QUEUE *pq,INT8U *pdata);
void	sInitialSci(INT8U sciid,INT16U wRxSize);	
INT8U sSciGetTxStatus(INT8U sciid);			
INT8U	sSciWrite(INT8U sciid,INT8U *pstart,INT8U ubLength);
			
/************************************************************************************
*Function name: sQInit																*
*Parameters:	pq: pointer to queue structure to be initialized					*
*				start:start address of ring buffer									*
*				size:the size of the ring buffer									*
*Description:	initialize a queue structure										*
*************************************************************************************/
void	sQInit(QUEUE *pq,INT8U *start,INT16U size)
{
	pq->pIn=start;
	pq->pOut=start;
	pq->pStart=start;
	pq->length=0;
	pq->size=size;
}


/************************************************************************************
*Function name:	sQDataIn															*
*Parameters:	pq:	pointer to queue structure to be initialized					*
*				data:the data to be inserted into the queue							*
*Returns:		cQBufNormal:data has been inserted into the queue					*
*				cQBufFull:the buffer is full										*
*Description:	insert a data into the queue										*
*************************************************************************************/
INT8U	sQDataIn(QUEUE	*pq,INT8U data)
{
	if(pq->length == pq->size)
	{
		return(cQBufFull);
	}
	else
	{
		*(pq->pIn) = data;
		pq->length ++;
//		ubSciTest[2] = pq->length;
		if(pq->pIn == (pq->pStart + (pq->size) - 1))	
		{
				pq->pIn = pq->pStart;
		}
		else
		{
			pq->pIn ++;
		}
		//ubSciTest[2]--;
		return(cQBufNormal);
	}
}
/************************************************************************************
*Function name:	sQDataOut															*
*Parameters:	pq:	pointer to queue structure to be initialized					*
*				pdata:the address to save the data									*
*Returns:		cQBufNormal:data has been inserted into the queue					*
*				cQBufEmpty:the buffer is empty										*
*Description:	Get a data from the queue											*
*************************************************************************************/
INT8U	sQDataOut(QUEUE *pq,INT8U *pdata)
{
	if(pq->length==0)
	{
		return(cQBufEmpty);
	}
	*pdata=*(pq->pOut);
	pq->length--;
	//if(pq->pOut==pq->pStart+pq->size-1)
	if(pq->pOut==pq->pStart+(pq->size)-1)	//
	{
		pq->pOut=pq->pStart;
	}
	else
	{
		pq->pOut++;
	}	
	return(cQBufNormal);
}

/************************************************************************************
*Function Name:	sInitialSci															*
*Parameters:	sciid:		sci id													*
*				*bRxBuf:	receive buffer start address							*
*				wRxSize:	receive buffer length									*
*				bTxBuf:		transmit buffer start address							*
*				wTxSize:	transmit buffer length									*
*				type:		sci type												*
*Descriptions:	assign and initialize the sci control struct to  sci				*
*************************************************************************************/

/************************************************************************************
*Function Name:	sInitialSci															*
*Parameters:	sciid:		sci id													*
*				*bRxBuf:	receive buffer start address							*
*				wRxSize:	receive buffer length									*
*				bTxBuf:		transmit buffer start address							*
*				wTxSize:	transmit buffer length									*
*				type:		sci type												*
*Descriptions:	assign and initialize the sci control struct to  sci				*
*************************************************************************************/

void	sInitialSci(INT8U sciid,INT16U wRxSize)
{
		SciStruct	*psci;
		QUEUE		*pq;
		
		psci=&SciList[bSciNo];
		pSciIndex[sciid]=psci;
		
		psci->pqRx=&QList[bSciNo];
		pq=psci->pqRx;
		sQInit(pq,pSciBuf,wRxSize);
		pSciBuf+=wRxSize;
		bSciNo++;
		
		psci->bTxStatus=cSciTxRdy;
		psci->ubTxLength=0;
					
		//psci->bSciType = type;
}




/************************************************************************************
*Function Name:	sSciRxISR															*
*Parameters:	sciid:		sci id													*
*Description:	This function is executed in Sci rx interrupt io2sci rx compare		*
*				interrupt.															*
*************************************************************************************/
void sSciRxISR(INT8U	sciid)
{
	INT8U           ubData;	
//	INT8U           ubDataTemp;
	SciStruct		*psci;
	QUEUE			*pq;
	
	psci = pSciIndex[sciid];
	pq = psci->pqRx;

	if(sciid == ComMainBrd)
	{
		ubData = USART_ReceiveData(USART3);
	}
	else if(sciid == ComDevice1)
	{
		ubData = USART_ReceiveData(USART2);
	}
	else if(sciid == ComDevice2)
	{
		ubData = USART_ReceiveData(UART4);
	}
	else if(sciid == ComDevice3)
	{
		ubData = USART_ReceiveData(UART5);
	}

	if(SysBit_1.Bits.SciIniOK == 1)
	{
		sQDataIn(pq,ubData);
	}
	
}

/************************************************************************************
*Function Name:	sSciTxISR															*
*Parameters:	sciid:		sci id													*
*Description:	This function is executed in Sci Tx interrupt io2sci Tx compare		*
*				interrupt.															*
*************************************************************************************/
void sSciTxISR(INT8U sciid)
{
//	INT8U 	data;
//	INT8U	temp;
	SciStruct		*psci;

	psci = pSciIndex[sciid];

	if(psci->ubTxLength > 0)
	{
		if(sciid == ComMainBrd)
		{
			USART_SendData(USART3, *(psci->pbTx));
		}
		else if(sciid == ComDevice1)
		{
			USART_SendData(USART2, *(psci->pbTx));
		}
		else if(sciid == ComDevice2)
		{
			USART_SendData(UART4, *(psci->pbTx));
		}
		else if(sciid == ComDevice3)
		{
			USART_SendData(UART5, *(psci->pbTx));
		}		 
		
		(psci->pbTx) ++;
		psci->ubTxLength --;
	}
	else
	{
		if(sciid == ComMainBrd)
		{
			USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
		}
		else  if(sciid == ComDevice1)
		{
			USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
		}
		else if(sciid == ComDevice2)
		{
			USART_ITConfig(UART4, USART_IT_TXE, DISABLE);
		}
		else if(sciid == ComDevice3)
		{
			USART_ITConfig(UART5, USART_IT_TXE, DISABLE);
		}
		
		psci->bTxStatus = cSciTxRdy;
	}			
}


	
/************************************************************************************
*Function Name:	sSciRead															*
*Parameters:	sciid:		sci id													*
*				*pBuf:		address to save data received							*
*Returns:		cSciRxBufEmpty:	receive  buffer is empty							*
*				cSciRxRdy:		get one byte data successfully						*
*Description:	This function is executed in AP										*
*************************************************************************************/
INT8U	sSciRead(INT8U	sciid,INT8U *pBuf)
{
		QUEUE			*pq;
		INT8U	temp;
		SciStruct		*psci;	
	
		psci=pSciIndex[sciid];
		pq=psci->pqRx;
	
	
		OS_ENTER_CRITICAL();
		temp=sQDataOut(pq,pBuf);
		OS_EXIT_CRITICAL();
	
		if(temp==cQBufEmpty)
		{
			return(cSciRxBufEmpty);
		}
		else 
		{
			return(cSciRxRdy);
		}
}

/************************************************************************************
*Function Name:	sSciGetTxStatus														*
*Parameters:	sciid:		sci id													*
*Returns:		sci tx status		cSciTxRdy										*
									cSciTxBusy										*
*Description:	Get the sci trasmit status											*
*************************************************************************************/	
INT8U	sSciGetTxStatus(INT8U sciid)
{
	SciStruct		*psci;
	
	psci=pSciIndex[sciid];
	
	return(psci->bTxStatus);
}	

/************************************************************************************
*Function Name:	sSciWrite															*
*Parameters:	sciid:		sci id													*
*				*pstart:	start address of data to be sent						*
*				wLength:	the length of data to be send							*
*Returns:		cSciTxBufFull:	transmit  buffer is empty							*
*				cSciTxRdy:		send one byte data successfully						*
*Description:	This function is executed in AP										*
*************************************************************************************/
INT8U	sSciWrite(INT8U sciid,INT8U *pstart,INT8U ubLength)
{
	SciStruct		*psci;
	
	psci = pSciIndex[sciid];
	
	if(psci->bTxStatus == cSciTxBusy)
	{
		return(cSciTxBusy);
	}
	
	OS_ENTER_CRITICAL();
	psci->pbTx = pstart;
	psci->ubTxLength = ubLength;
	psci->bTxStatus = cSciTxBusy;

	if(sciid == ComMainBrd)
	{
//		UART_SendData(UART1, *(psci->pbTx));
		USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
	}

	if(sciid == ComDevice1)
	{
//		UART_SendData(UART2, *(psci->pbTx));
		USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
	}

	if(sciid == ComDevice2)
	{
//		UART_SendData(UART2, *(psci->pbTx));
		USART_ITConfig(UART4, USART_IT_TXE, ENABLE);
	}
	
	if(sciid == ComDevice3)
	{
//		UART_SendData(UART1, *(psci->pbTx));
		USART_ITConfig(UART5, USART_IT_TXE, ENABLE);
	}
	
//	(psci->pbTx)++;
//	psci->ubTxLength--;
	OS_EXIT_CRITICAL();
	
	return(cSciTxRdy);
}




